module one_hot_mux #(
		parameter	IN_WIDTH	  =	20,
		parameter	SEL_WIDTH =   5, 
		parameter	OUT_WIDTH =	IN_WIDTH/SEL_WIDTH

	)
	(
		input [IN_WIDTH-1		:0]	mux_in,
		output[OUT_WIDTH-1	:0]	mux_out,
		input[SEL_WIDTH-1	:0]	sel

	);

	wire [IN_WIDTH-1	:0]	mask;
	wire [IN_WIDTH-1	:0]	masked_mux_in;
	wire [SEL_WIDTH-1:0]  	mux_out_gen [OUT_WIDTH-1:0]; 
	
	genvar i,j;
	
	//first selector masking
	generate 	// first_mask = {sel[0],sel[0],sel[0],....,sel[n],sel[n],sel[n]}
		for(i=0; i<SEL_WIDTH; i=i+1) begin : mask_loop
			assign mask[(i+1)*OUT_WIDTH-1 : (i)*OUT_WIDTH]	=	{OUT_WIDTH{sel[i]} };
		end
		
		assign masked_mux_in	= mux_in & mask;
		
		for(i=0; i<OUT_WIDTH; i=i+1) begin : lp1
			for(j=0; j<SEL_WIDTH; j=j+1) begin : lp2
				assign mux_out_gen [i][j]	=	masked_mux_in[i+OUT_WIDTH*j];
			end
			assign mux_out[i] = | mux_out_gen [i];
		end
	endgenerate
	
endmodule
	





module one_hot_2sel_mux #(
		parameter	IN_WIDTH	  =	20,
		parameter	SEL1_WIDTH =   5, //PORT_NUM
		parameter	SEL2_WIDTH =	4//VC_NUM_PER_PORT

	)
	(
		input [IN_WIDTH-1	:0]	mux_in,
		output						mux_out,
		input[SEL1_WIDTH-1:0]	sel1,
		input[SEL2_WIDTH-1:0]	sel2
	
	);

	wire [IN_WIDTH-1	:0]	first_mask;
	wire [IN_WIDTH-1	:0]	anded_level1;
	wire [SEL2_WIDTH-1:0] 	vcs_of_selected_port;
	wire [SEL1_WIDTH-1:0]  	same_vc_array [SEL2_WIDTH-1:0]; 
	
	genvar i,j;
	
	//first selector masking
	generate 	// first_mask = {sel[0],sel[0],sel[0],....,sel[n],sel[n],sel[n]}
		for(i=0; i<SEL1_WIDTH; i=i+1) begin : mask_loop
			assign first_mask[(i+1)*SEL2_WIDTH-1 : (i)*SEL2_WIDTH]	=	{SEL2_WIDTH{sel1[i]} };
		end
		
		assign anded_level1	= mux_in & first_mask;
		
		for(i=0; i<SEL2_WIDTH; i=i+1) begin : lp1
			for(j=0; j<SEL1_WIDTH; j=j+1) begin : lp2
				assign same_vc_array[i][j]	=	anded_level1[i+SEL2_WIDTH*j];
			end
			assign vcs_of_selected_port[i] = | same_vc_array[i];
		end
	endgenerate
	
	//second selector masking
	
	wire [SEL2_WIDTH-1:0]	anded_level2;
	assign   anded_level2	=   vcs_of_selected_port & sel2;
	assign	mux_out 			= | anded_level2;
	

	
endmodule



module one_hot_demux	#(
		parameter IN_WIDTH=5,
		parameter SEL_WIDTH=4,
		parameter OUT_WIDTH=IN_WIDTH*SEL_WIDTH
	)
	(
		input 	[SEL_WIDTH-1		:	0] demux_sel,//selectore
		input 	[IN_WIDTH-1			:	0] demux_in,//repeated
		output 	[OUT_WIDTH-1		:	0]	demux_out
	);

	genvar i,j;
	generate 
	for(i=0;i<SEL_WIDTH;i=i+1)begin :loop1
		for(j=0;j<IN_WIDTH;j=j+1)begin :loop2
				assign demux_out[i*IN_WIDTH+j] =	 demux_sel[i]	&	demux_in[j];
		end//for j
	end//for i
	endgenerate

	

endmodule
	